package game

import (
	gamemap "FlyFight/Internal/GameMap"
	player "FlyFight/Internal/Player"
	"FlyFight/Internal/cheese"
	"FlyFight/Internal/room"
	"encoding/binary"
	"errors"
	"log"
	"strconv"

	"github.com/gorilla/websocket"
)

func Init() {
	Gman=new(GamePool)
	Gman.Games=make(map[int]*Game)
}

func (p *GamePool)CheckExist(id int) bool {
	if p==nil{
		return false
	}
	p.Mu.RLock()
	defer p.Mu.RUnlock()
	if _,ok:=Gman.Games[id];ok{
		return true
	}
	return false
}

func (p *GamePool)Get(roomid int) *Game {
	if p==nil{
		return nil
	}
	p.Mu.RLock()
	defer p.Mu.RUnlock()
	if g,ok:=Gman.Games[roomid];ok{
		return g
	}
	return nil
}


func (p *GamePool)Add(g *Game) {
	if p==nil{
		return
	}
	p.Mu.Lock()
	defer p.Mu.Unlock()
	p.Games[g.Room.RoomId]=g
}

func (p *GamePool)DeleteGame(id int) error {
	if p==nil{
		return errors.New("nil pointer")
	}
	p.Mu.Lock()
	defer p.Mu.Unlock()
	if _,ok:=p.Games[id];ok{
		delete(p.Games,id)
		return nil
	}
	return errors.New("no such game")
}


func (g *Game)sendOthers(status Order,data []byte,uid int) {
	for _,gamer:=range g.Gamers {
		if gamer.Uid!=uid {
			gamer.Conn.WriteJSON(&Commend{
				Order: uint8(status),
				Data: data,
			})
		}
	}
}

func (g *Game)sendAll(status Order,data []byte) {
	for _,gamer:=range g.Gamers {
		gamer.Conn.WriteJSON(&Commend{
			Order: uint8(status),
			Data: data,
		})
	}
}

func(g *Game)NextTurn() {
	id:=g.turn.GoNext()
	name,err:=player.GetName(id)
	if err!=nil {
		log.Println(err)
		return
	}
	g.sendAll(newturn,[]byte(name))
}

func BuildGame(roomid int) *Game {
    g:=new(Game)
	g.Map=gamemap.Clone(gamemap.Ascent)
	g.Gamers=map[uint32]*Gamer{}
	g.Ready=make(chan struct{},4)
	g.Room=room.RoomList[roomid]

	g.buildTurn()
	return g
}

func (g *Game)DeleteGame() error{
	for _,v:=range g.Gamers{
		err:=v.Delete()
		if err!=nil{
			log.Println("delete gamer error"+strconv.Itoa(v.Uid))
			return err
		}
	}
	return nil
	
}

func (g *Game)waitReady(gamer *Gamer) {
	if len(g.Gamers)==g.Room.Len(){
		for i:=0;i<len(g.Gamers);i++{
			g.Ready<-struct{}{}
		}
	}
	<-g.Ready
	gamer.ReadySend()
}


func (g *Game)TryConnect(uid uint32,conn *websocket.Conn) error {
	if !g.Room.CheckExist(uid){
		return errors.New("uid not in room")
	}


	if len(g.Gamers)==4 {
		conn.Close()
		return errors.New("房间已满")
	}
	er,ok:=g.Gamers[uid]
	if ok{
		er.Conn.Close()
		er.Conn=conn
		return errors.New("玩家已存在")
	}

	g.Gamers[uid]=&Gamer{
		Buffer: make(chan []byte,10),
		Cheese: map[uint8]*cheese.FlyCh{},
		Conn: conn,
		Uid: int(uid),
		count: 0,
	}
	gamer:=g.Gamers[uid]
	g.waitReady(gamer)

	go gamer.AnalyzeRead(g)

	return nil
}
func (g *Game)AddCheese(data []byte,uid int){
	gamer,ok:=g.Gamers[uint32(uid)]
	if !ok {
		log.Println("uid not exist in game[addcheese]")
		return
	}
	x:=binary.BigEndian.Uint16(data)
	y:=binary.BigEndian.Uint16(data[2:])
	ctype:=uint8(data[4])

	err:=gamer.AddCheese(cheese.ChType(ctype),int(x),int(y),g)
	if err!=nil {
		log.Println("add cheese error")
		gamer.SendMessage([]byte("添加棋子失败请检查棋盘"))
		return
	}

}